package com.gyllr.futuresc;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.os.IBinder;
import android.support.v7.app.NotificationCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.RemoteViews;

import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_17;
import org.java_websocket.exceptions.InvalidFrameException;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

public class NotificationService extends Service {
    private static final int NO = 0;
    private static final int FORE_NOTIFICATION = 20170524;
    private static final int STATUS_CLOSE = 0;
    private static final int STATUS_CONNECT = 1;
    private static final int STATUS_MESSAGE = 2;

    private static final int WEBSOCKET_CONNECTING = 0;
    private static final int WEBSOCKET_OPEN = 1;
    private static final int WEBSOCKET_CLOSING = 2;
    private static final int WEBSOCKET_CLOSED = 3;

    private static WsClient wsClient = null;
    private NotificationManager manager = null;
    private MyReceiver receiver = null;

    private static String ip = null;
    private static String port = null;
    private static Map<String,String> headers = null;
    private static String foreTitle = "期货通知服务";
    private static String foreContent = "不要关闭我!";

    public NotificationService() {
        ip = BuildConfig.DEBUG ? "10.0.0.102" : "47.94.93.221";
        port = BuildConfig.DEBUG ? "80" :"80";
    }

    public static final String TAG = "NotificationService";

    private void Notice(String msg){
/*标准样式通知
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Title")//设置通知栏标题
                .setContentText(msg) //设置通知栏显示内容
//  .setNumber(number) //设置通知集合的数量
                .setTicker("Ticker") //通知首次出现在通知栏，带上升动画效果的
                .setWhen(System.currentTimeMillis())//通知产生的时间，会在通知信息里显示，一般是系统获取到的时间
                .setPriority(Notification.PRIORITY_DEFAULT) //设置该通知优先级
//  .setAutoCancel(true)//设置这个标志当用户单击面板就可以让通知将自动取消
                .setOngoing(false)//ture，设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                .setDefaults(Notification.DEFAULT_ALL);//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，可以组合
*/
        String title = "",content="",color="",time="";
//OPEN|l1609|2016-07-18 09:15:01|BUY|9170
        if(msg.startsWith("OPEN") || msg.startsWith("CLOSE")) {
            String[] m = msg.split("\\|");
            if (m.length != 5) return;
            String OpenOrClose = m[0];
            String Code = m[1];
            String DateTime = m[2];
            String BuyOrSell = m[3];
            String Price = m[4];

            title += Code;
            title += " ";
            title += BuyOrSell.trim().equals("BUY")    ? "买" : "卖";
            title += " ";
            title += OpenOrClose.trim().equals("OPEN") ? "开" : "平";

            //content += BuyOrSell.equals("BUY")  ? "高于" : "低于";
            time += "["+DateTime.trim().split(" ")[1]+"]";
            content += time;
            content += " ";
            content += Price;

            color = BuyOrSell.trim().equals("BUY")     ? "RED"  : "GREEN";
        } else {
            title = "提示消息";
            content = msg;
        }
//自定义通知样式
        //先设定RemoteViews
        RemoteViews view_custom = new RemoteViews(getPackageName(), R.layout.my_remote_view);
        view_custom.setTextViewText(R.id.txt_title,title);
        view_custom.setTextViewText(R.id.txt_content,content);
        if(color == "RED")
            view_custom.setTextColor(R.id.txt_title, Color.RED);
        else if(color == "GREEN")
            view_custom.setTextColor(R.id.txt_title, Color.GREEN);
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
        mBuilder.setSmallIcon(R.mipmap.ic_launcher)
                .setContent(view_custom)
                .setWhen(System.currentTimeMillis())//通知产生的时间，会在通知信息里显示，一般是系统获取到的时间
                .setPriority(Notification.PRIORITY_DEFAULT) //设置该通知优先级
                .setOngoing(false)//ture，设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                .setDefaults(Notification.DEFAULT_ALL);//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，可以组合

        manager.notify(NO, mBuilder.build());

        foreTitle = title;
        foreContent = content;
//更新前台服务的Notification
        setForeNotification(title,content);

        Log.v(TAG,"发到通知栏");
    }

    private void setForeNotification(String title,String content){
        NotificationCompat.Builder fBuilder = new NotificationCompat.Builder(this);
        fBuilder.setSmallIcon(R.mipmap.ic_launcher)//设置通知栏图标
                .setContentTitle(title)//设置通知栏标题
                .setContentText(content) //设置通知栏显示内容
                .setDefaults(Notification.FLAG_FOREGROUND_SERVICE);
        //Intent notificationIntent = new Intent(this, MainActivity.class);
        //PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        manager.notify(FORE_NOTIFICATION, fBuilder.build());
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() executed");

        TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        String deviceid = tm.getDeviceId();//获取智能设备唯一编号
        headers = new HashMap<String,String>();
        headers.put("IMEI",deviceid);

        manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        String address = String.format("ws://%s:%s", ip, port);
        Draft draft = new Draft_17();
        try {
            URI uri = new URI(address);
            wsClient = new WsClient(uri, draft, headers);
        } catch (URISyntaxException e) {
            e.printStackTrace();
            return;
        }
        //实例化IntentFilter对象
        IntentFilter filter = new IntentFilter();
        filter.addAction("ELITOR_CLOCK");
        //注册广播接收
        receiver = new MyReceiver();
        registerReceiver(receiver,filter);

        //创建Intent对象，action为ELITOR_CLOCK，附加信息为字符串“你该打酱油了”
        Intent intent = new Intent("ELITOR_CLOCK");
        intent.putExtra("msg","AM定时触发");

        //定义一个PendingIntent对象，PendingIntent.getBroadcast包含了sendBroadcast的动作。
        //也就是发送了action 为"ELITOR_CLOCK"的intent
        PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);

        //AlarmManager对象,注意这里并不是new一个对象，Alarmmanager为系统级服务
        AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);

        //设置闹钟从当前时间开始，每隔30s执行一次PendingIntent对象pi，注意第一个参数与第二个参数的关系

        //系统会强制设定最小间隔60秒,这个间隔时间不准确的
        //如果想要精确的或者5秒以内的定时器,请 post a delayed message or runnable to a Handler
        am.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),60*1000,pi);
        Log.d(TAG,"am settled");

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
        //Intent notificationIntent = new Intent(this, MainActivity.class);
        //PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setSmallIcon(R.mipmap.app)//设置通知栏图标
                .setContentTitle(foreTitle)//设置通知栏标题
                .setContentText(foreContent) //设置通知栏显示内容
                .setDefaults(Notification.FLAG_FOREGROUND_SERVICE);
                //.setContentIntent(pendingIntent);

        startForeground( FORE_NOTIFICATION, mBuilder.build());//第一个参数是通知的 id 唯一不要重复 不能为0
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand() executed");

        if(wsClient != null && wsClient.getReadyState() != WEBSOCKET_OPEN){//确认未连接
            try {
                wsClient.close();
                wsClient.connect();
            } catch(Exception e){
                setForeNotification(foreTitle + "  网络:×连接失败",foreContent);
            }
            Log.d(TAG,"建立连接");
        }
        else
            Log.d(TAG,"已连接");
        if(wsClient.getReadyState() == WEBSOCKET_OPEN) {
            setForeNotification(foreTitle + "  网络:●连接成功",foreContent);
        }else{
            setForeNotification(foreTitle + "  网络:×连接失败",foreContent);
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy() executed");
        stopForeground(true);
        unregisterReceiver(receiver);
        if(wsClient != null){
            wsClient.close();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    public class WsClient extends WebSocketClient {
        private static final String WSCLIENT_TAG = "WsClient";
        private boolean _isAlive = false;
        public WsClient(URI serverURI) {
            super(serverURI);
        }

        public WsClient(URI serverUri, Draft draft) {
            super(serverUri, draft);
        }
        public WsClient(URI serverUri, Draft draft, Map<String, String> headers) {
            super(serverUri, draft, headers);
        }
        @Override
        public void onOpen(ServerHandshake handShakeData) {
            _isAlive = true;
            Log.v(WSCLIENT_TAG,String.format("[Open：%s]", getURI()));
            setForeNotification(foreTitle + "  网络:●连接成功",foreContent);
        }

        @Override
        public void onMessage(String message) {
            Log.v(WSCLIENT_TAG,"Receive:" + message);
            Notice(message);
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {
            Log.v(WSCLIENT_TAG,String.format("[%sClose：%s]",remote?"remote":"client", getURI()));
        }

        @Override
        public void onWebsocketPong(WebSocket conn, Framedata f) {
            super.onWebsocketPong(conn, f);

            String value = parseFramedata(f);
            this._isAlive = true;
            Log.v(WSCLIENT_TAG,"<<收到pong");
        }

        @Override
        public void onWebsocketPing(WebSocket conn, Framedata f) {
            super.onWebsocketPing(conn, f);

            String value = parseFramedata(f);

            Log.v(WSCLIENT_TAG,"<<收到服务端ping");
            Log.v(WSCLIENT_TAG,">>回复pong");
        }

        @Override
        public void onError(Exception ex) {
            ex.printStackTrace();
        }

        public String parseFramedata(Framedata framedata){
            String result = "null";
            ByteBuffer buffer = framedata.getPayloadData();
            if(null == buffer){
                return result;
            }
            byte[] data = buffer.array();
            if(null != data && data.length > 0){
                return new String(data);
            }
            return result;
        }

        public void ping(){

            if( WEBSOCKET_OPEN != this.getReadyState() ) {
                String stat = "";
                switch(this.getReadyState())
                {
                    case 0 :
                        stat = "WEBSOCKET_CONNECTING";
                        break;
                    case 1 :
                        stat = "WEBSOCKET_OPEN";
                        break;
                    case 2 :
                        stat = "WEBSOCKET_CLOSING";
                        break;
                    case 3 :
                        stat = "WEBSOCKET_CLOSED";
                        break;
                    default:
                        stat="Unknown ReadyState";
                        break;
                }
                Log.v(WSCLIENT_TAG,stat);
                return;
            }

            Framedata f = new Framedata() {
                @Override
                public boolean isFin() {
                    return true;
                }

                @Override
                public boolean getTransfereMasked() {
                    return false;
                }

                @Override
                public Opcode getOpcode() {
                    return Opcode.PING;
                }

                @Override
                public ByteBuffer getPayloadData() {
                    return ByteBuffer.allocate(0);
                }

                @Override
                public void append(Framedata framedata) throws InvalidFrameException {

                }
            };
            try {
                this.getConnection().sendFrame(f);
                this._isAlive = false;
            }
            catch (Exception e) {
                e.printStackTrace();
                return;
            }

        }

        public boolean IsAlive(){return _isAlive;}
    }

    public class MyReceiver extends BroadcastReceiver
    {
        private static final String MYRECEIVER_TAG = "MyReceiver";
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String msg = intent.getStringExtra("msg");
            Log.v(MYRECEIVER_TAG,msg);

            if(wsClient.getReadyState() == WEBSOCKET_OPEN && wsClient.IsAlive()) {
                wsClient.ping();
                Log.v(MYRECEIVER_TAG,">>检测连接正常:send a ping!");
                setForeNotification(foreTitle + "  网络:●正常",foreContent);
            }
            else {
                try {
                    String address = String.format("ws://%s:%s", ip, port);
                    Draft draft = new Draft_17();
                    try {
                        URI uri = new URI(address);
                        wsClient = new WsClient(uri,draft,headers);
                        Log.v(MYRECEIVER_TAG,"**断线重连");
                        setForeNotification(foreTitle + "  网络:×断线重连中",foreContent);
                        wsClient.connect();
                        Thread.sleep(120);
                        Log.v(MYRECEIVER_TAG, "**readyState:" + wsClient.getReadyState());
                    } catch (URISyntaxException e) {
                        e.printStackTrace();
                        return;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    setForeNotification(foreTitle + "  网络:×重连失败",foreContent);
                    return;
                }
            }

        }

    }
}
